#include "SqlValue.h"

#include <string.h>
#include <stdlib.h>

namespace sql
{

Value::Value()
{
    setValue(NULL, type_undefined);
}

Value::Value(char* value, field_type type)
{
    setValue(value, type);
}

Value::Value(const Value& value)
{
    this->_value = value._value;
    this->_isNull = value._isNull;
    this->_type = value._type;
}

Value& Value::operator=(const Value& value)
{
    if (this != &value)
    {
        this->_value = value._value;
        this->_isNull = value._isNull;
        this->_type = value._type;
    }

    return *this;
}

bool Value::equals(Value& value)
{
    if (isNull())
    {
        return value.isNull();
    }

    switch (_type)
    {
    case type_int:
        return (asInteger() == value.asInteger());

    case type_text:
        return (asString().compare(value.asString()) == 0);

    case type_float:
        return (asDouble() == value.asDouble());

    case type_bool:
        return (asBool() == value.asBool());

    case type_time:
        return (asTime() == value.asTime());

    case type_undefined:
        return value.isIgnored();
    }

    return false;
}

void Value::setValue(char* value, field_type type)
{
    _isNull = true;
    _value.clear();
    _type = type;

    if (value)
    {
        _isNull = false;
        _value = value;
        _type = type;
    }
}

string Value::toSql(field_type type)
{
    if (isNull())
    {
        return "null";
    }

    if (type == type_text)
    {
        return "'" + quoteStr(asString()) + "'";
    }

    if (_type == type_time)
    {
        return intToStr(asInteger());
    }

    return asString();
}

string Value::toString()
{
    if (isNull())
    {
        return "null";
    }

    return asString();
}

bool Value::hasData() const
{
    if (isNull())
    {
        return false;
    }

    return _value.length() > 0;
}

string Value::asString() const
{
    if (_type == type_time)
    {
        time t(asInteger());
        return t.asString();
    }

    return _value;
}

integer Value::asInteger() const
{
    if (isNull())
    {
        return 0;
    }

#if defined(_MSC_VER) && (_MSC_VER > 1700)
    return std::stoll(_value);
#else
#if (__cplusplus >= 201103L)
    return std::stoll(_value);
#else
    return atoll(_value.c_str());
#endif
#endif
}

unsigned int Value::asUInt() const
{
    if (isNull())
    {
        return 0;
    }

#if defined(_MSC_VER) && (_MSC_VER > 1700)
    return (unsigned int)std::stoll(_value);
#else
#if (__cplusplus >= 201103L)
    return (unsigned int)std::stoll(_value);
#else
    return (unsigned int)atoll(_value.c_str());
#endif
#endif
}

double Value::asDouble() const
{
    if (isNull())
    {
        return 0.0;
    }

    return atof(_value.c_str());
}

bool Value::asBool() const
{
    if (isNull())
    {
        return false;
    }

    return (_value.compare("1") == 0);
}

time Value::asTime() const
{
    time dt(asInteger());
    return dt;
}

void Value::setIgnored()
{
    _isNull = false;
    _value.clear();
    _type = type_undefined;
}

void Value::setNull()
{
    _isNull = true;
    _value.clear();
}

void Value::setString(string value)
{
    _isNull = false;
    _value = value;
    _type = type_text;
}

//CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4996)

void Value::setInteger(integer value)
{
    _isNull = false;

#if defined(_MSC_VER) && (_MSC_VER > 1700)
    _value = std::to_string(value);
#else
#if (__cplusplus >= 201103L)
    _value = std::to_string(value);
#else
    char buffer[128] = { 0 };
    snprintf(buffer, sizeof(buffer), "%d", (int)value);
    _value = buffer;
#endif
#endif
    _type = type_int;
}

void Value::setDouble(double value)
{
    char buffer[128];

    sprintf(buffer, "%0.8f", value);

    _isNull = false;
    _value = buffer;
    _type = type_float;
}

#pragma warning(default : 4996)

void Value::setBool(bool value)
{
    _isNull = false;
    _value = (value ? "1" : "0");
    _type = type_bool;
}

void Value::setTime(time value)
{
    time t(value);
    _isNull = false;
    setInteger(t.asInteger());
    _type = type_time;
}

bool Value::isIgnored() const
{
    return (type_undefined == _type) && (!_isNull);
}

bool Value::isNull() const
{
    return _isNull;
}


//sql eof
};
